package hierarchydisplay;

import java.awt.Graphics;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;

/* composite contain other nodes and point to them through connections */
public class CompositeNode extends Node implements ICompositeNode {
	
	public CompositeNode(HierarchyDisplay hd) {
		super(hd);
	}

	protected List<Connection> connections = new LinkedList<Connection>();
	
	protected List<Node> children = new LinkedList<Node>();
	
	protected boolean validChildren = false; 
	
	
	/* Draw node, its children and links to the children */
	public void draw(Graphics g) {
		super.draw(g);
		
		/* draw children */
		for (int i1 = 0; i1 < getChildCount(); i1++) {
			getChildAt(i1).draw(g);				
		}
		
		/* draw connections */
		Iterator it = connections.iterator();
		while (it.hasNext()) {
			((Connection)it.next()).draw(g);
		}
	}
	
	/* Generate node layout. Propagates to children */
	public void calculateLayout(int y, int stepY, int leftX, int rightX) {
		super.calculateLayout(y, stepY, leftX, rightX);
		
		int cnt = getChildCount();
		
		/* calculate connections */
		connections.clear();
		for (int i1 = 0; i1 < cnt; i1++) {
			connections.add(new Connection(this, getChildAt(i1)));
		}
				
		int cell = (rightX - leftX) / getNumLeaves();
		int pos = 0;
		for (int i1 = 0; i1 < cnt; i1++) {
			int nextPos = pos + getChildAt(i1).getNumLeaves();
			getChildAt(i1).calculateLayout(
					y + stepY, stepY, 
					leftX + cell * pos, 
					leftX + cell * nextPos);
			pos = nextPos;
		}			
	}
	
	/* update children */
	public void childrenChanged() {
		/* mark that chilren are invalid */
		validChildren = false;
		
		/* invalidate hierarchy layout */
		hierarchyDisplay.invalidateLayout();
	}
	
	/* Calculate the total number of leaves under the node */
	public int getNumLeaves() {
		int numLeaves = 0;
		for (int i1 = 0; i1 < getChildCount(); i1++) {
			numLeaves += getChildAt(i1).getNumLeaves();				
		}
		return numLeaves == 0 ? 1 : numLeaves;
	}
	
	public void addChild(Node child) {
		if (null == child) throw new IllegalArgumentException("Cannot add 'null' as a child."); 
		children.add(child);
	}

	/* get i-th child */
	public Node getChildAt(int i) {
		return children.get(i);
	}
	
	/* get number of children */
	public int getChildCount() {
		return children.size();
	}
}
